home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Collections: Topik
/
Topik - Disk 37 - Games 3 (19xx)(Topik Public Domain)(PD)[WB].zip
/
Topik - Disk 37 - Games 3 (19xx)(Topik Public Domain)(PD)[WB].adf
/
RUMMY
/
SOURCE
/
autoturn.c.pp
/
autoturn.c
Wrap
C/C++ Source or Header
|
1991-02-24
|
23KB
|
805 lines
/* AUTOTURN.C
* This contains the functions for the program to decide what to do
*/
#include <proto/all.h>
#include <stdlib.h>
#include <math.h>
#include <intuition/intuition.h>
#include <string.h>
#include "defns.h"
#include "externs.h"
VOID autoturn(cp,np,pp)
struct playerinfo *cp,*np,*pp;
{
register USHORT i,n,p,takefup,cc=cp->nchld,gtemp;
register struct condset *s;
char buf[3];
/* deselect fup,fdp*/
gtemp = RemoveGList(wind,&stdgad[FUPG],2);
RefreshGList(&stdgad[FUPG],wind,NULL,2);
stdgad[FUPG].Flags &= ~SELECTED;
stdgad[FDPG].Flags &= ~SELECTED;
TXTOUT(180,21,1,0,cp->name);
TXTOUT(MESX,MESY,7,0,"... is thinking ...");
cp->hand[0] = fup[fuptc]; /*test how well next card from fup integrates with other cards*/
buildsets(cp);
for(i=0;i<=ncs;i++) score(&cs[i],cp); /*initial scores for sets*/
n=mutexcl(cp); /*generate non-mutually exclusive combination of submissible sets*/
if(!n) /*fup card not very useful, and not submissible*/
{ /*try fdp card instead*/
TXTOUT(MESX,MESY,7,0,"Takes the facedown card. ");
takefup=0;
maintainmem(cp,pp,np,fup[fuptc],GONEPAST);
maintainmem(cp,pp,np,fup[fuptc],CURRPLRDROPD);
cp->hand[0]=NEXTFDP;
cp->mem[CARD2(cp->hand[0])] |= CURRPLRHOLDS;
buildsets(cp);
for(i=0;i<=ncs;i++) score(&cs[i],cp);
mutexcl(cp);
}
else
{
takefup=1;
TXTOUT(MESX,MESY,7,0,"Takes the faceup card. ");
NEXTFUP; /*fup card will be used so remove it from pack*/
maintainmem(cp,pp,np,cp->hand[0],CURRPLRHOLDS);
}
for(p=3;p;p--)
{
for(n=0;n<=ncs;n++) if(selcs[n].ns) /*some cards in set*/
{
s=&selcs[n];
if((p==3 && s->ns==3 || p==2) && s->type&SUB) autosubset(s,cp); /*submit set*/
else if(p==1 && s->type&ADD) autoaddset(s,cp); /*add to set*/
}
}
/*now drop card with lowest score*/
for(i=0,p=60000,n=500;i<=cp->nchld;i++)
if(!ISNUL(cp->hand[i]) && (cdsc[i]<p || n==500) && (i!=0 || !takefup)) p=cdsc[n=i]; /*new lowest*/
PUTFUP(cp->hand[n]);
DRAWFUP;
maintainmem(cp,pp,np,cp->hand[n],CURRPLRDROPD);
cp->hand[n]=nulcard;
if(!ISNUL(cp->hand[0]))
{ /*copy selected card to body of hand*/
for(i=1;i<=cp->nchld && !ISNUL(cp->hand[i]);i++);
cp->hand[i]=cp->hand[0];
}
compacthand(cp->hand,&cp->nchld);
REMHAND(cp);
if(cp->viewcard) disphand(cp); else hidecards(cp);
cc-=cp->nchld;
if(cc)
{
sortdispset();
stci_d(buf,cc);
TXTOUT(MESX+25*8,MESY,7,0,buf);
TXTOUT(MESX+27*8,MESY,7,0,"submitted - Hit continue");
}
else
{
TXTOUT(MESX+25*8,MESY,7,0,"None submitted - Hit continue");
}
if(!contplay) WAITCONT;
AddGList(wind,&stdgad[FUPG],gtemp,2,NULL);
TXTOUT(MESX,MESY,7,0," ");
TXTOUT(180,21,1,0," ");
}
VOID autosubset(struct condset *s,struct playerinfo *p)
{
register struct card *t=s->set;
register USHORT i,d,n,samesuit=1,samenum=1;
for(i=0,n=0;i<=p->nchld;i++) if(!ISNUL(p->hand[i])) n++;
d=s->ns;
if(d==n+1)
{/* ensure at least one card will be left when finished*/
for(i=0;i<=d;i++) if(CDEQU(p->hand[i],t[d])) s->uc&=~(1<<i);
d--;
}
for(i=2;i<=d;i++)
{ /*final check on validity of set*/
if(t[i-1].n!=t[i].n) samenum=0;
if(t[i-1].s!=t[i].s) samesuit=0;
}
if(d<3 || !(samesuit || samenum)) return; /*rejected submission attempt*/
if(samesuit)
{ /*check set is continuous*/
for(i=2;i<=d;i++)
if((t[i-1].n!=t[i].n-1) && !(t[i-1].n==KING && t[i].n==ACE)) return; /*rejected*/
}
n=s->uc<<1;
for(i=0;i<=p->nchld;i++) if((n>>=1)&1) p->hand[i]=nulcard; /*this card about to be submitted*/
for(i=0;i<=5 && fupset[i]->ncard;i++); /*find empty set*/
fupset[i]->ncard=d;
if(samesuit) for(n=1;n<=d;n++)
{
fupset[i]->cards[n+t[1].n-1]=t[n];
maintainmem(NULL,NULL,NULL,t[n],INFUPSET);
}
else for(n=1;n<=d;n++)
{
fupset[i]->cards[n]=t[n];
maintainmem(NULL,NULL,NULL,t[n],INFUPSET);
}
s->ns=s->nd=0; /*remove all cards from set*/
}
VOID autoaddset(struct condset *s,struct playerinfo *p)
{
register struct card *fsc,*phc;
register USHORT *fsn,phn,i,j,f,l,used;
fsc=fupset[s->addtoset]->cards;
fsn=&fupset[s->addtoset]->ncard;
phc=p->hand;
phn=p->nchld;
for(f=1;ISNUL(fsc[f]);f++); /*find first card of set*/
l=f+(*fsn)-1;
if(fsc[f].s==fsc[f+1].s && s->type&SUITSET) /*same suit*/
{
if(s->type&TOSTART)
{
if(s->set[1].n==fsc[f].n-1 && s->set[1].s==fsc[f].s)
{
for(i=0,used=1;i<=phn;i++) if(CDEQU(s->set[1],phc[i]) && !ISNUL(s->set[1]))
{
phc[i]=nulcard;
used=0; /*card has not already been used*/
}
if(!used)
{
fsc[--f]=s->set[1];
maintainmem(NULL,NULL,NULL,s->set[1],INFUPSET);
(*fsn)++;
for(j=1;j<=s->nd;j++) if(s->dep[j].n==fsc[f].n-1 && s->dep[j].s==fsc[f].s)
{
for(i=0,used=1;i<=phn;i++) if(CDEQU(s->dep[j],phc[i]) && !ISNUL(s->dep[j]))
{
phc[i]=nulcard;
used=0; /*card not already used*/
}
if(!used)
{
fsc[--f]=s->dep[j];
maintainmem(NULL,NULL,NULL,s->dep[j],INFUPSET);
(*fsn)++;
}
else
{/*exit function - no more additions possible*/
s->nd=s->ns=0;
return;
}
}
}
else
{/*exit function - no more additions possible*/
s->nd=s->ns=0;
return;
}
}
}
else if(s->type&TOEND)
{
if(((s->set[1].n==fsc[l].n+1 && s->set[1].n!=2) || (fsc[l].n==KING && s->set[1].n==ACE))
&& s->set[1].s==fsc[l].s)
{
for(i=0,used=1;i<=phn;i++) if(CDEQU(s->set[1],phc[i]) && !ISNUL(s->set[1]))
{
phc[i]=nulcard;
used=0; /*card not already used*/
}
if(!used)
{
fsc[++l]=s->set[1];
maintainmem(NULL,NULL,NULL,s->set[1],INFUPSET);
(*fsn)++;
for(j=1;j<=s->nd;j++) if(((s->dep[j].n==fsc[l].n+1 && s->dep[j].n!=2) || (fsc[l].n==KING && s->dep[j].n==ACE))
&& s->dep[j].s==fsc[l].s)
{
for(i=0,used=1;i<=phn;i++) if(CDEQU(s->dep[j],phc[i]) && !ISNUL(s->dep[j]))
{
phc[i]=nulcard;
used=0; /*card not already used*/
}
if(!used)
{
fsc[++l]=s->dep[j];
maintainmem(NULL,NULL,NULL,s->dep[j],INFUPSET);
(*fsn)++;
}
else
{/*exit function - no more additions possible*/
s->nd=s->ns=0;
return;
}
}
}
else
{/*exit function - no more additions possible*/
s->nd=s->ns=0;
return;
}
}
}
}
else if(fsc[f].n==fsc[f+1].n && s->set[1].n==fsc[f].n && s->type&NUMSET && *fsn==3)
{
for(i=0,used=1;i<=phn && used;i++) if(CDEQU(s->set[1],phc[i]) && !ISNUL(s->set[1]))
{
phc[i]=nulcard;
used=0; /*card not already used*/
fsc[++l]=s->set[1];
maintainmem(NULL,NULL,NULL,s->dep[j],INFUPSET);
(*fsn)++;
}
}
s->ns=s->nd=0; /*remove all cards from set*/
}
VOID buildsets(struct playerinfo *p)
{
register USHORT i,n,nchld=p->nchld,s;
register struct card *h=p->hand;
USHORT nconc,setfound; /*next condensed set, number of consecutive cards*/
for(i=0;i<=3;i++)
{ /*initialise arrays*/
for(n=0;n<=15;n++) ss[i].c[n] = nulcard;
ss[i].nc=0;
}
for(i=0;i<=32;i++)
{
cs[i].type = NOTSET;
cs[i].ns = cs[i].nd = cs[i].score = cs[i].ig = cs[i].addtoset = cs[i].uc= 0;
for(n=0;n<=8;n++) cs[i].set[n]=cs[i].dep[n]=nulcard;
}
for(i=0;i<=13;i++) ns[i].nc=0;
for(i=0;i<=nchld;i++)
{ /*separate hand into sets*/
ns[h[i].n].c[++ns[h[i].n].nc]=h[i]; /*add card to numset*/
ss[h[i].s].c[h[i].n]=h[i]; /*add card to suit set*/
if(h[i].n==ACE) ss[h[i].s].c[14]=h[i];
ss[h[i].s].nc++;
}
/*card ss[s].c[n] has suit s and number n.*/
ncs=0;
for(i=0;i<=3;i++)
if(ss[i].nc)
{ /*convert suit set to condensed form*/
nconc=setfound=0;
for(n=1;n<=15;n++)
{ /*look for submissible sets*/
if(!ISNUL(ss[i].c[n])) nconc++;
else
{
if(nconc>=3)
{ /*submissible set*/
if(setfound) ncs++; /*current set already has submissible subset*/
while(nconc) cs[ncs].set[++cs[ncs].ns]=ss[i].c[n-nconc--];
setfound=1; /*current record now has a submissible set*/
cs[ncs].type = SUITSET | SUB;
}
else
{
if((cs[ncs].nd || cs[ncs].ns) &&
(n-nconc)-max(cs[ncs].dep[cs[ncs].nd].n,cs[ncs].set[cs[ncs].ns].n)>=(p->nchld<4?p->nchld:4))
{
ncs++;
setfound=0; /*no set in current record*/
}
while(nconc) cs[ncs].dep[++cs[ncs].nd]=ss[i].c[n-nconc--];
cs[ncs].type = SUITSET | SUB;
}
}
}
if(cs[ncs].ns || cs[ncs].nd) cs[ncs++].type = SUITSET | SUB;
else cs[ncs].ns=cs[ncs].nd=0;
}
cs[ncs].type = NOTSET;
/*detect cards which can be added to existing suitsets*/
for(i=0;i<=3;i++)
{
if(ss[i].nc) /*check some cards in set*/
{
for(n=1;n<=14;n++)
{
if(!ISNUL(ss[i].c[n]))
{
setfound=0;
for(s=0;s<=5 && !setfound && fupset[s]->ncard;s++)
{
if(ISNUL(fupset[s]->cards[n]))
{
if(fupset[s]->cards[n-1].n==n-1 && !ISNUL(fupset[s]->cards[n-1])
&& fupset[s]->cards[n-1].s==i && fupset[s]->cards[n-2].s==i)
{ /*can add after set s*/
if(cs[ncs].type!=NOTSET) ncs++; /*current set already used*/
else cs[ncs].ns=cs[ncs].nd=0; /*current set no good - throw it away*/
cs[ncs].set[++cs[ncs].ns]=ss[i].c[n];
cs[ncs].addtoset=s;
cs[ncs].type = ADD | SUITSET | TOEND;
setfound=1;
}
else if(fupset[s]->cards[n+1].n==n+1 && fupset[s]->cards[n+1].s==i && fupset[s]->cards[n+2].s==i)
{ /*can add before set s*/
if(cs[ncs].type!=NOTSET || (cs[ncs].nd && cs[ncs].dep[1].s!=ss[i].c[n].s)) ncs++;
cs[ncs].set[++cs[ncs].ns]=ss[i].c[n];
cs[ncs].addtoset=s;
cs[ncs].type= ADD | SUITSET | TOSTART;
setfound=1;
ncs++; /*move to new set*/
}
}
}
if(!setfound)
{ /*add to dependants*/
if((cs[ncs].ns || cs[ncs].nd)
&& ((n-max(cs[ncs].set[cs[ncs].ns].n,cs[ncs].dep[cs[ncs].nd].n))>=4)
|| (ss[i].c[n].s!=(cs[ncs].ns==0?cs[ncs].dep[1].s:cs[ncs].set[1].s)))
{ /*start new set*/
if(cs[ncs].type!=NOTSET) ncs++;
else cs[ncs].ns=cs[ncs].nd=0;
}
cs[ncs].dep[++cs[ncs].nd]=ss[i].c[n];
}
}
}
}
}
if(cs[ncs].ns) ncs++;
else cs[ncs].nd=0;
/*copy numsets to condensed sets*/
for(i=1;i<=13;i++)
{
if(ns[i].nc==1)
{ /*can card be added to existing set*/
setfound=0;
for(s=0;s<=5 && !setfound && fupset[s]->ncard;s++)
if(fupset[s]->cards[1].n==ns[i].c[1].n && fupset[s]->cards[2].n==ns[i].c[1].n)
{ /*can add card this set*/
cs[ncs].addtoset=s;
cs[ncs].set[++cs[ncs].ns]=ns[i].c[1];
cs[ncs++].type= ADD | NUMSET;
setfound=1;
}
if(!setfound)
{
cs[ncs].dep[++cs[ncs].nd]=ns[i].c[1];
cs[ncs++].type = SUB | NUMSET;
}
}
else if(ns[i].nc==2)
{
cs[ncs].dep[1]=ns[i].c[1];
cs[ncs].dep[2]=ns[i].c[2];
cs[ncs].type = NUMSET | SUB;
cs[ncs++].nd=2;
}
else if(ns[i].nc>=3)
{
for(n=1;n<=ns[i].nc;n++) cs[ncs].set[n]=ns[i].c[n];
cs[ncs].type = NUMSET | SUB;
cs[ncs++].ns=ns[i].nc;
}
}
for(i=0;i<=ncs;i++)
for(n=1;n<=cs[i].ns;n++)
for(s=setfound=0;s<=nchld && !setfound;s++) if(setfound=CDEQU(cs[i].set[n],h[s])) cs[i].uc|=(1<<s);
}
VOID score(struct condset *c,struct playerinfo *p)
{
register USHORT i,n,j,last,m,s;
USHORT gap,next;
struct card t[5];
c->score = 0;
if(c->type&NUMSET)
{
for(n=1;n<=c->ns;n++) c->score+=(c->set[n].n*8+(n>1?1100:0))+300;
for(n=1;n<=c->nd;n++) c->score+=((15-c->dep[n].n)*4+(n>1?1300:0));
for(n=1;n<=4;n++) t[n]=nulcard;
if(c->nd)
{
s=c->dep[1].n;
for(n=1;n<=c->nd;n++) t[c->dep[n].s]=c->dep[n];
}
else
{
s=c->set[1].n;
for(n=1;n<=c->ns;n++) t[c->set[n].s]=c->set[n];
}
for(n=1;n<=4;n++) if(ISNUL(t[n]))
{
m=p->mem[CARD(s,n)];
if(!(m&INFUPSET))
{
c->score+=100+15-s;
if(!(m&NEXTPLRHOLDS)) c->score+=70;
if(!(m&PREVPLRHOLDS)) c->score+=40;
if(!(m&GONEPAST)) c->score+=100;
if(m&(NEXTPLRDROPD | PREVPLRDROPD)) c->score+=100;
}
}
else c->score+=(16-t[n].n)*4;
}
else /*score suitset*/
{
if(ISNUL(c->set[1])) last=c->dep[1].n;
else if(ISNUL(c->dep[1])) last=c->set[1].n;
else last=min(c->dep[1].n,c->set[1].n);
if(c->type&SUB)
{
c->score+=c->ns*500+c->nd*100;
for(i=n=1;(i<=c->ns || n<=c->nd) && !exgm && !quit;)
{
if(c->set[i].n<=c->dep[n].n && i<=c->ns || n>c->nd)
{
if(c->set[i].n==ACE && i>1) c->score+=(last==KING?1200:(7-(13-last))*130)+15*9+100;
else if(c->set[i].n!=last)
c->score+=(c->set[i].n-last==1?1200:(6-(c->set[i].n-last-1))*100)+c->set[i].n*9+100;
else c->score+=(15-last)*9+100;
last=c->set[i++].n;
}
else
{
if(c->dep[n].n==ACE && n>1) c->score+=(last==KING?1200:(6-(13-last))*110)+15*5+80;
else if(c->dep[n].n!=last)
c->score+=(c->dep[n].n-last==1?1200:(6-(c->dep[n].n-last-1))*90)+(15-c->dep[n].n)*5+80;
else c->score+=(15-last)*5+80;
last=c->dep[n++].n;
}
}
}
else if(c->type&ADD)
{
for(i=n=1;(i<=c->ns || n<=c->nd) && !exgm && !quit;)
{
if(c->set[i].n<=c->dep[n].n && i<=c->ns || n>c->nd)
{
if(c->set[i].n==ACE && i>1) next = 14;
else next=c->set[i].n;
if(last!=c->set[i].n)
c->score+=(next-last==1?1200:(7-(next-last-1))*100)+c->set[i].n*9+100;
else c->score+=(15-last)*9+100;
last=c->set[i++].n;
}
else
{
if(c->dep[n].n==ACE && i>1) next = 14;
else next=c->dep[n].n;
if(next-last==1) c->score+=1200+c->dep[n].n*8+80;
else if(last!=next) c->score+=(6-(next-last-1))*90+c->dep[n].n*5+80;
else c->score+=(15-last)*5+80;
last=c->dep[n++].n;
}
}
}
if(!ISNUL(c->set[1])) s=c->set[1].s;
else s=c->dep[1].s;
if(ISNUL(c->set[1])) last=c->dep[1].n;
else if(ISNUL(c->dep[1])) last=c->set[1].n;
else last=min(c->dep[1].n,c->set[1].n);
for(i=n=1;(i<=c->ns || n<=c->nd) && !exgm && !quit;)
{
if(c->set[i].n<=c->dep[n].n && i<=c->ns || n>c->nd)
{
gap=c->set[i].n-last-1;
next=c->set[i++].n;
}
else
{
gap=c->dep[n].n-last-1;
next=c->dep[n++].n;
}
for(j=last+1;j<next;j++)
{
m=p->mem[CARD(s,n)];
if(!(m&INFUPSET))
{
c->score+=90/gap+15-s;
if(!(m&NEXTPLRHOLDS)) c->score+=70/gap;
if(!(m&PREVPLRHOLDS)) c->score+=70/gap;
if(!(m&GONEPAST)) c->score+=90/gap;
if(m&(NEXTPLRDROPD | PREVPLRDROPD)) c->score+=90/gap;
}
last=next;
}
}
}
if(c->type&SUB && p->nchld<=2) c->score=0; /*less than useless*/
if(c->type&ADD && p->nchld<=2) c->score+=15000; /*ensure high score for addable sets when submission is impossible*/
if(c->type&NUMSET && c->nd==2) c->score+=500;
c->score+=c->ns*600;
}
USHORT mutexcl(struct playerinfo *p)
{
register USHORT i,j,k,w,x;
long l;
struct card c,*s;
USHORT bias, /*toward 1:numset, 2:suitset 3:set with higher score*/
pass, /*number of passes to be made with different biases*/
nxsts, /*next start set*/
psperbias, /*number of passes to be made for each bias at different start sets*/
best=0,pn,chng,currst,pm,sc,cdscs[53];
if(p->level==1)
{/*easiest level*/
bias=1; pass=1; nxsts=0; psperbias=1;
}
else if(p->level==1)
{/*best level*/
bias=1; pass=3; nxsts=0; psperbias=ncs;
}
else if(p->level<=5)
{/*fairly easy*/
l=rand();
bias=1;
pass=1;
if((nxsts=l&31)>ncs) nxsts=ncs;
if((psperbias=(l>>5&31)+1)>ncs>>1 && ncs!=1) psperbias=ncs>>1;
}
else
{/*fairly good play*/
l=rand();
bias=1;
pass=3;
if((nxsts=l&31)>ncs) nxsts=ncs;
if((psperbias=(l>>5&31)+1)>ncs) psperbias=ncs;
}
while(pass--)
{
for(currst=nxsts,pn=psperbias,chng=1;pn && chng;pn--)
{
chng=0; /*change made flag*/
for(i=0;i<=ncs;i++) testcs[i]=cs[i];
for(i=currst,pm=0;!pm || i!=currst;i=i>=ncs?0:i+1)
{
pm=1;
for(j=(i>=ncs?0:i+1);j!=i;j=j>=ncs?0:j+1)
{
if(w=testcs[i].uc&testcs[j].uc)
{/*collision between sets*/
w<<=1;k=0;
while(w)
{
while(!((w>>=1)&1) && w) k++;
c=p->hand[k]; /*card causing collision*/
if(w && ((bias==1 && testcs[i].type&NUMSET && testcs[j].type&SUITSET)
|| (bias==2 && testcs[i].score >= testcs[j].score)
|| (bias==3 && testcs[i].score < testcs[j].score)))
{ /*reduce set i*/
chng=1;
for(x=1;!CDEQU(testcs[i].set[x],c) && x<=testcs[i].ns;x++);
testcs[i].set[x]=nulcard;
if(c.n==ACE && testcs[i].set[testcs[i].ns].n==ACE) testcs[i].set[testcs[i].ns]=nulcard;
compacthand(testcs[i].set,&testcs[i].ns);
checksets(&testcs[i],p);
score(&testcs[i],p);
}
else if(w)
{ /*reduce set j*/
chng=1;
for(x=1;!CDEQU(testcs[j].set[x],c) && x<=testcs[j].ns;x++);
testcs[j].set[x]=nulcard;
if(c.n==ACE && testcs[j].set[testcs[j].ns].n==ACE) testcs[j].set[testcs[j].ns]=nulcard;
compacthand(testcs[j].set,&testcs[j].ns);
checksets(&testcs[j],p);
score(&testcs[j],p);
}
}
}
}
}
for(j=0,sc=0;j<=ncs;j++) sc+=testcs[j].score;
if(sc>best)
{ /*new best set*/
best=sc;
for(j=0;j<=ncs;j++) selcs[j]=testcs[j];
}
if(currst==ncs) currst=0; else currst++;
if(bias==3) bias=1; else bias++;
}
}
for(j=0;j<=p->nchld;j++) cdscs[CARD2(p->hand[j])]=0; /*zeroise scores of player cards*/
/* The section below prevents the autoplayer being left with just two
* cards, which cannot be submitted (min 3), and meaning it must wait
* for cards to arrive which can be added to existing sets, which the
* other players will also be looking out for.
* NB. this will only reduce submissions by one card, and only where
* permissible.
*/
/*work out number of cards to be submitted by this combination of sets*/
for(i=0,w=0;i<=ncs;i++) if(selcs[i].type&ADD)
{
w++; /*at least one card can be submitted*/
for(j=1,x=selcs[i].set[1].n;j<=selcs[i].nd;j++) if(x+1==selcs[i].dep[j].n || x-1==selcs[i].dep[j].n)
{
w++; x=selcs[i].dep[j].n;
}
}
else if(selcs[i].type&SUB) w+=selcs[i].ns;
if(p->nchld-w==2) /*retain one further card to enable later submissions*/
{
for(i=0,w=0;i<=ncs && !w;i++) if(selcs[i].type&SUB && selcs[i].ns>=4)
{/*prevent submission of one of the cards of the set*/
for(j=selcs[i].nd;j>=2;j--) selcs[i].dep[j]=selcs[i].dep[j-1]; /*create space in dep list*/
selcs[i].dep[1]=selcs[i].set[selcs[i].ns--];
selcs[i].nd++;
w=1; /*finished*/
cdscs[CARD2(selcs[i].dep[1])]+=20000; /*ensure this card retained*/
}
else if(selcs[i].type&ADD)
{
if(selcs[i].type&NUMSET || (selcs[i].type&SUITSET
&& selcs[i].set[1].n!=selcs[i].dep[1].n-1 && selcs[i].set[1].n!=selcs[i].dep[1].n+1))
{/* only one addable card - remove it to the dep list*/
for(j=selcs[i].nd;j>=2;j--) selcs[i].dep[j]=selcs[i].dep[j-1]; /*create space in dep list*/
selcs[i].dep[1]=selcs[i].set[1];
selcs[i].set[1]=nulcard;
selcs[i].ns--; selcs[i].nd++;
selcs[i].type&= ~ADD;
selcs[i].type|= SUB;
w=1;
cdscs[CARD2(selcs[i].dep[1])]+=20000; /*ensure this card retained*/
}
else
{/* reduce number of addable cards of this set to just one*/
for(j=selcs[i].nd;j>=2;j--) selcs[i].dep[j]=selcs[i].dep[j-1]; /*create space in dep list*/
selcs[i].dep[1]=nulcard;
selcs[i].nd++;
cdscs[CARD2(selcs[i].dep[2])]+=20000; /*ensure this card retained*/
w=1;
}
}
}
/*generate card scores here*/
for(i=0;i<=ncs;i++)
{
if(selcs[i].type&SUITSET)
{
if(selcs[i].ns)
{
for(j=1;j<=selcs[i].ns;j++) cdscs[CARD2(selcs[i].set[j])]+=selcs[i].score;
for(j=1;j<=selcs[i].nd;j++)
{
w=selcs[i].dep[j-1].n;x=selcs[i].dep[j].n;
k=selcs[i].dep[j+1].n;
if(selcs[i].dep[j].n<selcs[i].set[1].n)
cdscs[CARD2(selcs[i].dep[j])]+=(selcs[i].score*j)/22 +
((j>1?(w<x?x-w:w-x):0) * selcs[i].score)/30 +
((j<selcs[i].nd?(k<x?x-k:k-x):0) * selcs[i].score)/30;
else cdscs[CARD2(selcs[i].dep[j])]+=(selcs[i].score*(9-j))/22 +
((j>1?(w<x?x-w:w-x):0) * selcs[i].score)/30 +
((j<selcs[i].nd?(k<x?x-k:k-x):0) * selcs[i].score)/30;
}
}
else /*no submissible cards*/
{
for(j=1;j<=selcs[i].nd;j++)
{
w=selcs[i].dep[j-1].n;x=selcs[i].dep[j].n;
k=selcs[i].dep[j+1].n;
cdscs[CARD2(selcs[i].dep[j])]+=selcs[i].score +
((j>1?(w<x?x-w:w-x):0) * selcs[i].score)/12 +
((j<selcs[i].nd?(k<x?x-k:k-x):0) * selcs[i].score)/12;
}
}
}
else /*numset*/
{
for(j=1;j<=selcs[i].ns;j++) cdscs[CARD2(selcs[i].set[j])]+=selcs[i].score*(j==4?(1/2):1);
for(j=1;j<=selcs[i].nd;j++) cdscs[CARD2(selcs[i].dep[j])]+=selcs[i].score*(j==4?(1/2):1);
}
}
for(j=0;j<=p->nchld;j++) cdsc[j]=cdscs[CARD2(p->hand[j])];
l=rand();
if(p->level==1) return (USHORT)(l&1);
else if(p->level<=9)
{
if(p->level<(l%11)+1) return (USHORT)(l&256);
}
/* the next loop checks to see if any cards can be added to an existing
* set after the acquisition of one further card, a facility which was
* overlooked in the original program design
*/
for(i=0;i<=p->nchld;i++)
{
for(j=0;j<5 && fupset[j]->ncard;j++)
{
s=fupset[j]->cards;
for(k=1;k<=13 && ISNUL(s[k]);k++);
w=k+fupset[j]->ncard-1; /*last card*/
if(s[k].s==s[k+1].s && s[k].s==p->hand[i].s) /*suitset*/
{
x=p->hand[i].n;
if(x==s[k].n-2 && !(p->mem[CARD(x+1,s[k].s)]&INFUPSET)) cdsc[i]+=1500;
if(x==s[w].n+2 && !(p->mem[CARD(x-1,s[k].s)]&INFUPSET)) cdsc[i]+=1500;
if(x==ACE && s[w].n==QUEEN && !(p->mem[CARD(KING,s[k].s)]&INFUPSET)) cdsc[i]+=1500;
}
}
}
if(p->nchld==1)
{
for(i=0;i<=ncs;i++) if(selcs[i].type&ADD && CDEQU(selcs[i].set[1],p->hand[0])) return 1;
return 0; /* last card not addable, so recommend to ignore it*/
}
/* the section below causes the last selected card to be dropped if it
* only belongs to one set of two cards, and the other member is about
* to be dropped
*/
j=cdsc[k=0];
for(i=1;i<=p->nchld;i++) if(cdsc[i]<j) j=cdsc[k=i];
if(k!=0 && cdsc[0]>1690 /* || cdsc[0]>2200*/) return 1; /*keep last selected card*/
else
{
for(i=w=x=0;i<=ncs;i++)
{
for(j=1;j<=selcs[i].nd;j++) if(CDEQU(selcs[i].dep[j],p->hand[0]) && selcs[i].nd==2 && !selcs[i].ns)
{
w++;
x=i;
}
}
if(w==1)
{
if(CDEQU(selcs[x].dep[1],p->hand[0])) j=2; else j=1;
for(i=0;i<=p->nchld;i++) if(CDEQU(p->hand[i],selcs[x].dep[j]) && i==k) return 0; /*drop card*/
}
}
for(j=0;j<=ncs;j++) if(selcs[j].uc&1) return 1; /* last chosen card being submitted in set*/
return 0; /*last selected card not being submitted in a set,
and not within two of an adjacent card*/
}
VOID checksets(struct condset *c,struct playerinfo *p)
{ /*reconstruct reduced set*/
register USHORT i,n=0,nconc,setfound;
struct card t[16];
for(i=0;i<=15;i++) t[i]=nulcard;
if(c->type&SUITSET && c->type&SUB)
{
for(i=1;i<=c->ns;i++) if(c->set[i].n==ACE && i>1) t[14]=c->set[i];
else t[c->set[i].n]=c->set[i];
for(i=1;i<=c->nd;i++) if(c->dep[i].n==ACE && i>1) t[14]=c->dep[i];
else t[c->dep[i].n]=c->dep[i];
n=c->nd+c->ns;
nconc=0;
c->nd=c->ns=0;
for(i=1;i<=15;i++)
{
if(!ISNUL(t[i])) nconc++;
else
{
if(nconc>=3) while(nconc) c->set[++c->ns]=t[i-nconc--];
else while(nconc) c->dep[++c->nd]=t[i-nconc--];
}
}
}
else if(c->type&NUMSET && c->type&SUB)
{
if(c->ns==2 || c->ns==1) for(c->nd=0;c->ns;)c->dep[++c->nd]=c->set[c->ns--];
}
if(!(c->ns || c->nd)) c->type=NOTSET; /*no cards in this set*/
else for(n=1,c->uc=0;n<=c->ns;n++)
for(i=setfound=0;i<=p->nchld && !setfound;i++) if(setfound=CDEQU(c->set[n],p->hand[i])) c->uc|=(1<<i);
}